import { camelCase, upperFirst, snakeCase } from 'lodash';
import genConfig from '@/config/generator';
import { GenTable, GenTableColumn } from '@/models/tool';

// 添加索引签名接口
interface TypeMap {
  [key: string]: string;
}

/**
 * 代码生成器工具类
 */
class GenUtils {
  /**
   * 初始化表信息
   * @param genTable 业务表
   */
  public static initTable(genTable: GenTable, operName: string): void {
    genTable.className = this.convertClassName(genTable.tableName);
    genTable.packageName = genConfig.packageName;
    genTable.moduleName = 'system';
    genTable.businessName = this.getBusinessName(genTable.tableName);
    genTable.functionName = this.replaceText(genTable.tableComment);
    genTable.functionAuthor = genConfig.author;
    genTable.createBy = operName;
    genTable.tplCategory = 'crud';
    genTable.genType = '0';  // 默认为zip下载
  }

  /**
   * 初始化列信息
   * @param column 列信息
   */
  public static initColumnField(column: GenTableColumn, table: GenTable): void {
    // 设置字段名称
    const columnName = column.columnName;
    // 设置Java类型
    column.javaType = this.getJavaType(column.columnType);
    // 设置Java字段名
    column.javaField = this.getJavaField(columnName);

    // 默认设置
    if (column.columnComment === null || column.columnComment === '') {
      column.columnComment = column.columnName;
    }
    if (column.isInsert === undefined) column.isInsert = '1';
    if (column.isEdit === undefined) column.isEdit = '1';
    if (column.isList === undefined) column.isList = '1';
    if (column.isQuery === undefined) column.isQuery = '1';
    if (column.queryType === undefined) column.queryType = 'EQ';
    if (column.htmlType === undefined) column.htmlType = this.getHtmlType(column);
    if (column.sort === undefined) column.sort = 0;

    // 特殊情况处理
    // 主键、自增设置
    if (this.isPrimaryKey(column.columnName) || 'id' === column.columnName) {
      column.isPk = '1';
      column.isRequired = '0';
      column.isInsert = '0';
      column.isEdit = '0';
    } else {
      column.isPk = '0';
      column.isIncrement = '0';
    }
    
    // 是否必填处理
    if (this.isRequiredField(column.columnName)) {
      column.isRequired = '1';
    }
  }

  /**
   * 表名转换成类名，例如：sys_user -> SysUser
   * @param tableName 表名
   * @returns 类名
   */
  public static convertClassName(tableName: string): string {
    // 如果有表前缀并且自动去除前缀设置为true，则去掉表前缀
    let className = tableName;
    
    if (genConfig.autoRemovePre && genConfig.tablePrefix) {
      const tablePrefixes = genConfig.tablePrefix.split(',');
      for (const prefix of tablePrefixes) {
        if (tableName.startsWith(prefix)) {
          className = tableName.substring(prefix.length);
          break;
        }
      }
    }
    
    return this.convertToCamelCase(className, true);
  }

  /**
   * 获取业务名
   * @param tableName 表名
   * @returns 业务名
   */
  public static getBusinessName(tableName: string): string {
    // 如果有表前缀并且自动去除前缀设置为true，则去掉表前缀
    let businessName = tableName;
    
    if (genConfig.tablePrefix) {
      const tablePrefixes = genConfig.tablePrefix.split(',');
      for (const prefix of tablePrefixes) {
        if (tableName.startsWith(prefix)) {
          businessName = tableName.substring(prefix.length);
          break;
        }
      }
    }
    
    // 将下划线风格转为驼峰，但不大写首字母
    return this.convertToCamelCase(businessName, false);
  }

  /**
   * 替换文本中的非法字符
   * @param text 文本
   * @returns 替换后的文本
   */
  public static replaceText(text: string | undefined): string {
    if (!text) return '';
    // 替换表注释中的非法字符，例如空格、特殊字符等
    return text.replace(/[^\u4e00-\u9fa5a-zA-Z0-9\-_]/g, '');
  }

  /**
   * 获取Java类型
   * @param columnType 列类型
   * @returns Java类型
   */
  public static getJavaType(columnType: string): string {
    if (!columnType) return 'String';
    
    // 移除括号内容和空格
    const type = columnType.toLowerCase().replace(/\(.*\)/, '').trim();
    
    // 遍历类型映射表
    for (const dbType of Object.keys(genConfig.typeMap.javaTypeMap)) {
      if (type.includes(dbType)) {
        return (genConfig.typeMap.javaTypeMap as TypeMap)[dbType];
      }
    }
    
    return 'String';
  }

  /**
   * 获取TypeScript类型
   * @param columnType 列类型
   * @returns TypeScript类型
   */
  public static getTypeScriptType(columnType: string): string {
    if (!columnType) return 'string';
    
    // 移除括号内容和空格
    const type = columnType.toLowerCase().replace(/\(.*\)/, '').trim();
    
    // 遍历类型映射表
    for (const dbType of Object.keys(genConfig.typeMap.tsTypeMap)) {
      if (type.includes(dbType)) {
        return (genConfig.typeMap.tsTypeMap as TypeMap)[dbType];
      }
    }
    
    return 'string';
  }

  /**
   * 获取Sequelize类型
   * @param columnType 列类型
   * @returns Sequelize类型
   */
  public static getSequelizeType(columnType: string): string {
    if (!columnType) return 'STRING';
    
    // 移除括号内容和空格
    const type = columnType.toLowerCase().replace(/\(.*\)/, '').trim();
    
    // 遍历类型映射表
    for (const dbType of Object.keys(genConfig.typeMap.sequelizeTypeMap)) {
      if (type.includes(dbType)) {
        return (genConfig.typeMap.sequelizeTypeMap as TypeMap)[dbType];
      }
    }
    
    return 'STRING';
  }

  /**
   * 获取列长度
   * @param columnType 列类型
   * @returns 列长度
   */
  public static getColumnLength(columnType: string): number {
    if (!columnType) return 255;
    const matches = columnType.match(/\((\d+)\)/);
    return matches ? parseInt(matches[1]) : 255;
  }

  /**
   * 获取HTML类型
   * @param column 列信息
   */
  public static getHtmlType(column: GenTableColumn): string {
    const columnType = column.columnType;
    const columnName = column.columnName;
    
    // 根据字段名判断类型
    if (this.isDateType(columnType)) {
      return 'datetime';
    }
    if (this.isContentType(columnName)) {
      return 'editor';
    }
    if (this.isImageType(columnName)) {
      return 'imageUpload';
    }
    if (this.isFileType(columnName)) {
      return 'fileUpload';
    }
    if (this.isNumberType(columnType)) {
      return 'input';
    }
    
    // 默认为文本框
    return 'input';
  }

  /**
   * 将下划线风格的字段名转换为驼峰风格
   * @param name 字段名
   * @param capitalized 是否大写首字母
   * @returns 驼峰风格名称
   */
  public static convertToCamelCase(name: string, capitalized: boolean = false): string {
    if (!name) return '';
    const camelName = camelCase(name);
    return capitalized ? upperFirst(camelName) : camelName;
  }

  /**
   * 将驼峰风格转换为下划线风格
   * @param name 驼峰风格名称
   * @returns 下划线风格名称
   */
  public static convertToSnakeCase(name: string): string {
    if (!name) return '';
    return snakeCase(name);
  }

  /**
   * 将字段名转换为Java属性名
   * @param name 字段名
   * @returns Java属性名
   */
  public static getJavaField(name: string): string {
    return this.convertToCamelCase(name);
  }

  /**
   * 判断是否为主键
   * @param columnName 列名
   * @returns 是否为主键
   */
  public static isPrimaryKey(columnName: string): boolean {
    return /^id$|^.*_id$/.test(columnName.toLowerCase());
  }

  /**
   * 判断字段是否为必填
   * @param columnName 列名
   * @returns 是否必填
   */
  public static isRequiredField(columnName: string): boolean {
    return !/^is_|^has_/.test(columnName.toLowerCase());
  }

  /**
   * 判断是否为日期类型
   * @param columnType 列类型
   * @returns 是否为日期类型
   */
  public static isDateType(columnType: string): boolean {
    if (!columnType) return false;
    return /date|time|timestamp/i.test(columnType);
  }

  /**
   * 判断是否为内容字段
   * @param columnName 列名
   * @returns 是否为内容类型
   */
  public static isContentType(columnName: string): boolean {
    if (!columnName) return false;
    const name = columnName.toLowerCase();
    return name.includes('content') || name.includes('description');
  }

  /**
   * 判断是否为图片字段
   * @param columnName 列名
   * @returns 是否为图片类型
   */
  public static isImageType(columnName: string): boolean {
    if (!columnName) return false;
    const name = columnName.toLowerCase();
    return name.includes('image') || name.includes('picture') || name.includes('avatar');
  }

  /**
   * 判断是否为文件字段
   * @param columnName 列名
   * @returns 是否为文件类型
   */
  public static isFileType(columnName: string): boolean {
    if (!columnName) return false;
    const name = columnName.toLowerCase();
    return name.includes('file');
  }

  /**
   * 判断是否为数值类型
   * @param columnType 列类型
   * @returns 是否为数值类型
   */
  public static isNumberType(columnType: string): boolean {
    if (!columnType) return false;
    const type = columnType.toLowerCase();
    return type.includes('int') || type.includes('number') || type.includes('float') || 
           type.includes('double') || type.includes('decimal');
  }

  /**
   * 获取字段默认排序
   * @param columnName 列名
   * @returns 默认排序
   */
  public static getSort(columnName: string): number {
    if (columnName === 'id') return 1;
    if (columnName.includes('_id')) return 2;
    if (columnName === 'name') return 3;
    if (columnName.includes('_time')) return 90;
    if (columnName === 'create_time') return 91;
    if (columnName === 'update_time') return 92;
    return 10;
  }

  /**
   * 检查字段是否为超类字段
   * @param tplCategory 模板类型
   * @param javaField Java字段名
   * @returns 是否为超类字段
   */
  public static isSuperColumn(tplCategory: string, javaField: string): boolean {
    if (!javaField) return false;
    
    // 判断是否属于基类字段
    if (genConfig.superClassFields.includes(javaField)) {
      return true;
    }
    
    // 树表特有字段
    if (tplCategory === 'tree' && (javaField === 'parentId' || javaField === 'ancestors' || javaField === 'children')) {
      return true;
    }
    
    return false;
  }
}

export default GenUtils; 